package com.ruoyi.washer.common;

import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.washer.domain.XwDevice;
import com.ruoyi.washer.domain.XwProduct;
import com.ruoyi.washer.domain.XwPurchaseOrder;
import com.ruoyi.washer.mapper.XwDeviceMapper;
import com.ruoyi.washer.mapper.XwProductMapper;
import com.ruoyi.washer.mapper.XwPurchaseOrderMapper;
import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator;
import com.wechat.pay.contrib.apache.httpclient.cert.CertificatesManager;
import com.wechat.pay.contrib.apache.httpclient.constant.WechatPayHttpHeaders;
import com.wechat.pay.contrib.apache.httpclient.exception.HttpCodeException;
import com.wechat.pay.contrib.apache.httpclient.exception.NotFoundException;
import com.wechat.pay.contrib.apache.httpclient.notification.Notification;
import com.wechat.pay.contrib.apache.httpclient.notification.NotificationHandler;
import com.wechat.pay.contrib.apache.httpclient.notification.NotificationRequest;
import com.wechat.pay.contrib.apache.httpclient.util.AesUtil;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.*;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.text.SimpleDateFormat;
import java.util.Base64;
import java.util.Calendar;
import java.util.Date;
import java.util.UUID;

@Service
public class WxPayTool {

    @Value("${wx.appid}")
    private String appid;

    @Value("${wx.appsecret}")
    private String secret;

    @Value("${wx.mch_id}")
    private String mchId;

    @Value("${wx.key_v2}")
    private String key_v2;

    @Value("${wx.key_v3}")
    private String key_v3;

    @Value("${wx.notify_url}")
    private String notify_url;

    @Value("${wx.refund_notify_url}")
    private String refund_notify_url;

    @Value("${wx.private_key}")
    private String private_key;

    @Value("${wx.mch_serial_no}")
    private String mch_serial_no;

    private static final Logger logger = LoggerFactory.getLogger(WxPayTool.class);



    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private XwDeviceMapper xwDeviceMapper;

    @Autowired
    private XwProductMapper xwProductMapper;

    @Autowired
    private XwPurchaseOrderMapper xwPurchaseOrderMapper;

    @Transactional
    public JSONObject initBuyPay(String deviceSn,int index,String productId,String openId)throws Exception{
        JSONObject jsonObject;
        XwDevice xwDevice=xwDeviceMapper.selectXwDeviceByDeviceSn(deviceSn);
        XwProduct xwProduct=xwProductMapper.selectXwProductByProductId(Long.parseLong(productId));
        int amount=(int)(Float.parseFloat(xwProduct.getProductPrice())*100);
        jsonObject=createOrder(openId,"购买洗衣球",amount);
        XwPurchaseOrder xwPurchaseOrder=new XwPurchaseOrder();
        xwPurchaseOrder.setPayDate(new Date());
        xwPurchaseOrder.setPayType("2");
        xwPurchaseOrder.setOpenId(openId);
        xwPurchaseOrder.setDeviceType(xwDevice.getDeviceType());
        xwPurchaseOrder.setBuyType("2");
        xwPurchaseOrder.setDeviceSn(deviceSn);
        xwPurchaseOrder.setPayState("1");
        xwPurchaseOrder.setPayAmount(new BigDecimal(amount));
        xwPurchaseOrder.setOutTradeNo(jsonObject.getString("outTradeNo"));
        xwPurchaseOrder.setCreatedTime(new Date());
        xwPurchaseOrderMapper.insertXwPurchaseOrder(xwPurchaseOrder);
        return jsonObject;
    }


    public JSONObject createOrder(String openid, String description, int money) throws Exception {
        try {
            Security.setProperty("crypto.policy", "unlimited");
            //唯一的内部订单号（后续支付、关单、查单、退款都跟这个相关）
            // String outTradeNo = stringToMD5(System.currentTimeMillis() + "" + RandomUtil.randomString(32));
            String outTradeNo =getOutTradeNo();
            System.out.println("outTradeNo=========="+outTradeNo);
//			如果用字符串存储私钥就用这个
            PrivateKey merchantPrivateKey = PemUtil
                    .loadPrivateKey(new ByteArrayInputStream(private_key.getBytes("utf-8")));
            // PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(new FileInputStream("私钥文件路径");
            // 获取证书管理器实例
            CertificatesManager certificatesManager = CertificatesManager.getInstance();
            // 向证书管理器增加需要自动更新平台证书的商户信息
            certificatesManager.putMerchant(mchId,
                    new WechatPay2Credentials(mchId,
                            new PrivateKeySigner(mch_serial_no, merchantPrivateKey)),
                    key_v3.getBytes(StandardCharsets.UTF_8));

            CloseableHttpClient httpClient = WechatPayHttpClientBuilder.create()
                    .withMerchant(mchId, mch_serial_no, merchantPrivateKey)
                    .withValidator(new WechatPay2Validator(certificatesManager.getVerifier(mchId)))
                    .build();

            HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi");
            httpPost.addHeader("Accept", "application/json");
            httpPost.addHeader("Content-type", "application/json; charset=utf-8");

            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectMapper objectMapper = new ObjectMapper();

            ObjectNode rootNode = objectMapper.createObjectNode();
            rootNode.put("mchid", mchId)
                    .put("appid", appid)
                    .put("description", description)
                    .put("notify_url", notify_url)
                    .put("out_trade_no", outTradeNo);
            rootNode.putObject("amount")
                    .put("total", money);
            rootNode.putObject("payer")
                    .put("openid", openid);
            rootNode.putObject("settle_info")
                    .put("profit_sharing", true);

            objectMapper.writeValue(bos, rootNode);

            httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));
            CloseableHttpResponse response = httpClient.execute(httpPost);

            String bodyAsString = EntityUtils.toString(response.getEntity());
            System.out.println("bodyAsString============="+bodyAsString);
            String timestamp = (System.currentTimeMillis() / 1000) + "";
            String nonce = RandomUtil.randomString(32).toUpperCase();
            StringBuilder builder = new StringBuilder();
            builder.append(appid).append("\n");
            builder.append(timestamp).append("\n");
            builder.append(nonce).append("\n");
            JsonNode node = objectMapper.readTree(bodyAsString);
            builder.append("prepay_id="
                    + node.get("prepay_id").toString().substring(1, node.get("prepay_id").toString().length() - 1))
                    .append("\n");
            String ciphertext = sign(builder.toString().getBytes(StandardCharsets.UTF_8));
            System.out.println("ciphertext=========="+ciphertext);
            System.out.println("prepay_id=========="+node.get("prepay_id").toString());
            /*
            Map<String, String> map = new HashMap<String, String>();
            map.put("nonceStr", nonce);
            map.put("package", "prepay_id="
                    + node.get("prepay_id").toString().substring(1, node.get("prepay_id").toString().length() - 1));
            map.put("timeStamp", timestamp);
            map.put("paySign", ciphertext);
            map.put("signType", "RSA");
            map.put("outTradeNo", outTradeNo);
            //小程序前端获取pay就可以使用wx.requestPayment了
             */
            JSONObject JSONObject=new JSONObject();
            JSONObject.put("nonceStr", nonce);
            JSONObject.put("package", "prepay_id="
                    + node.get("prepay_id").toString().substring(1, node.get("prepay_id").toString().length() - 1));
            JSONObject.put("timeStamp", timestamp);
            JSONObject.put("paySign", ciphertext);
            JSONObject.put("signType", "RSA");
            JSONObject.put("outTradeNo", outTradeNo);
            return JSONObject;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    /*
        支付成功后的回调接口
     */
    public void payNotifyAll(HttpServletRequest request)throws Exception{
        String encryptedBody=getBody(request);
        String decryptedBody=decryptOrder(encryptedBody);
        JSONObject jsonObject=JSONObject.parseObject(decryptedBody);
        String trade_state=jsonObject.getString("trade_state");
        if(trade_state!=null&&trade_state.equals("SUCCESS")){
            String transactionId=jsonObject.getString("transaction_id");
            String total=jsonObject.getJSONObject("amount").getString("total");
            String outTradeNo=jsonObject.getString("out_trade_no");
            XwPurchaseOrder xwPurchaseOrder=xwPurchaseOrderMapper.selectXwPurchaseOrderByOutTradeNo(outTradeNo);
            xwPurchaseOrder.setPrepayId(transactionId);
            xwPurchaseOrder.setPayState("3");//支付成功
            xwPurchaseOrder.setPayAmountReal(new BigDecimal(total));
            xwPurchaseOrder.setOutTradeNo(outTradeNo);
            xwPurchaseOrder.setUpdatedTime(new Date());
            xwPurchaseOrderMapper.updateXwPurchaseOrder(xwPurchaseOrder);
        }
    }

    /*
    获取body
     */
    public String getBody(HttpServletRequest request)throws Exception{
        String body="";
        BufferedReader reader=null;
        try {
            reader = request.getReader();
            String line;
            StringBuilder inputString = new StringBuilder();
            while ((line = reader.readLine()) != null) {
                inputString.append(line);
            }
            body = inputString.toString();
            reader.close();
        }catch (Exception e){
            e.printStackTrace();
            throw e;
        }finally {
            if(reader!=null){
                reader.close();
                reader=null;
            }
        }
        return body;
    }

    /*
        支付回调处理
     */
    public JSONObject wechatPayNotify(HttpServletRequest request)throws Exception{
        JSONObject jsonObject=new JSONObject();
        String wechatPaySerial = request.getHeader(WechatPayHttpHeaders.WECHAT_PAY_SERIAL);
        String nonce = request.getHeader(WechatPayHttpHeaders.WECHAT_PAY_NONCE);
        String timestamp = request.getHeader(WechatPayHttpHeaders.WECHAT_PAY_TIMESTAMP);
        String signature = request.getHeader(WechatPayHttpHeaders.WECHAT_PAY_SIGNATURE);
        String body="";
        BufferedReader reader=null;
        logger.info("wechatPaySerial=========="+wechatPaySerial);
        logger.info("nonce=========="+nonce);
        logger.info("timestamp=========="+timestamp);
        logger.info("signature=========="+signature);
        try {
            reader = request.getReader();
            String line;
            StringBuilder inputString = new StringBuilder();
            while ((line = reader.readLine()) != null) {
                inputString.append(line);
            }
            body = inputString.toString();
            reader.close();
        }catch (Exception e){
            e.printStackTrace();
            throw e;
        }finally {
            if(reader!=null){
                reader.close();
                reader=null;
            }
        }
        logger.info("body=========="+body);

        logger.info("body0=========="+decryptOrder(body));

        logger.info("Verify=========="+signVerify(wechatPaySerial,body,signature));




        // 构建request，传入必要参数
        NotificationRequest res = new NotificationRequest.Builder().withSerialNumber(wechatPaySerial)
                .withNonce(nonce)
                .withTimestamp(timestamp)
                .withSignature(signature)
                .withBody(body)
                .build();
        logger.info("body1==========");
        CertificatesManager certificatesManager = CertificatesManager.getInstance();
        logger.info("body2==========");
        Verifier verifier = certificatesManager.getVerifier(mchId);
        logger.info("body3==========");
        NotificationHandler handler = new NotificationHandler(verifier, key_v3.getBytes(StandardCharsets.UTF_8));
        logger.info("body4==========");
        // 验签和解析请求体
        Notification notification = handler.parse(res);
        logger.info("notification回调通知数据：" + notification.toString());
        // 解析开数据
        String decryptData = notification.getDecryptData();
        logger.info("decryptData回调解析数据：" + decryptData);

        if (StringUtils.isEmpty(decryptData)) {
            return null;
        }
        return jsonObject;
    }

    /*支付通知和退款通知给服务器的回调 请求头验签*/
    public boolean signVerify(String serialNumber, String message, String signature) {
        try {
            PrivateKey merchantPrivateKey =PemUtil
                    .loadPrivateKey(new ByteArrayInputStream(private_key.getBytes("utf-8")));
            // 获取证书管理器实例
            CertificatesManager certificatesManager = CertificatesManager.getInstance();
            // 向证书管理器增加需要自动更新平台证书的商户信息
            certificatesManager.putMerchant(mchId,
                    new WechatPay2Credentials(mchId,
                            new PrivateKeySigner(mch_serial_no, merchantPrivateKey)),
                    key_v3.getBytes(StandardCharsets.UTF_8));
            // 从证书管理器中获取verifier
            Verifier verifier = certificatesManager.getVerifier(mchId);
            return verifier.verify(serialNumber, message.getBytes(StandardCharsets.UTF_8), signature);
        } catch (HttpCodeException | NotFoundException | IOException | GeneralSecurityException e) {
            e.printStackTrace();
        }
        return false;
    }
    /*支付通知和退款通知给服务器的回调 解密报文*/
    public String decryptOrder(String body) {
        try {
            AesUtil util = new AesUtil(key_v3.getBytes(StandardCharsets.UTF_8));
            ObjectMapper objectMapper = new ObjectMapper();
            JsonNode node = objectMapper.readTree(body);
            JsonNode resource = node.get("resource");
            String ciphertext = resource.get("ciphertext").textValue();
            String associatedData = resource.get("associated_data").textValue();
            String nonce = resource.get("nonce").textValue();
            return util.decryptToString(associatedData.getBytes("utf-8"), nonce.getBytes("utf-8"), ciphertext);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    /*关单*/
    public void closeOrder(String outTradeNo) {
        try {
            PrivateKey merchantPrivateKey = PemUtil
                    .loadPrivateKey(new ByteArrayInputStream(private_key.getBytes("utf-8")));
            // 获取证书管理器实例
            CertificatesManager certificatesManager = CertificatesManager.getInstance();
            // 向证书管理器增加需要自动更新平台证书的商户信息
            certificatesManager.putMerchant(mchId,
                    new WechatPay2Credentials(mchId,
                            new PrivateKeySigner(mch_serial_no, merchantPrivateKey)),
                    key_v3.getBytes(StandardCharsets.UTF_8));

            CloseableHttpClient httpClient = WechatPayHttpClientBuilder.create()
                    .withMerchant(mchId, mch_serial_no, merchantPrivateKey)
                    .withValidator(new WechatPay2Validator(certificatesManager.getVerifier(mchId)))
                    .build();

            HttpPost httpPost = new HttpPost(
                    "https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/" + outTradeNo + "/close");
            httpPost.addHeader("Accept", "application/json");
            httpPost.addHeader("Content-type", "application/json; charset=utf-8");

            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectMapper objectMapper = new ObjectMapper();

            ObjectNode rootNode = objectMapper.createObjectNode();
            rootNode.put("mchid", mchId);

            objectMapper.writeValue(bos, rootNode);

            httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));
            CloseableHttpResponse response = httpClient.execute(httpPost);
            System.out.println(response.getStatusLine().getStatusCode()); // 状态码204就关单成功，无响应内容
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /*查支付状态的单*/
    public String queryOrder(String outTradeNo) throws Exception{
        String bodyAsString="";
        try {
            PrivateKey merchantPrivateKey = PemUtil
                    .loadPrivateKey(new ByteArrayInputStream(private_key.getBytes("utf-8")));
            // 获取证书管理器实例
            CertificatesManager certificatesManager = CertificatesManager.getInstance();
            // 向证书管理器增加需要自动更新平台证书的商户信息
            certificatesManager.putMerchant(mchId,
                    new WechatPay2Credentials(mchId,
                            new PrivateKeySigner(mch_serial_no, merchantPrivateKey)),
                    key_v3.getBytes(StandardCharsets.UTF_8));
            CloseableHttpClient httpClient = WechatPayHttpClientBuilder.create()
                    .withMerchant(mchId, mch_serial_no, merchantPrivateKey)
                    .withValidator(new WechatPay2Validator(certificatesManager.getVerifier(mchId)))
                    .build();
            URIBuilder uriBuilder = new URIBuilder("https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/"
                    + outTradeNo + "?mchid=" + mchId);
            HttpGet httpGet = new HttpGet(uriBuilder.build());
            httpGet.addHeader("Accept", "application/json");
            CloseableHttpResponse response = httpClient.execute(httpGet);
            bodyAsString = EntityUtils.toString(response.getEntity());
            System.out.println(bodyAsString);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bodyAsString;
    }
    /*查退款状态的单
    {
    "amount": {
        "currency": "CNY",
        "discount_refund": 0,
        "from": [],
        "payer_refund": 1,
        "payer_total": 1,
        "refund": 1,
        "refund_fee": 0,
        "settlement_refund": 1,
        "settlement_total": 1,
        "total": 1
    },
    "channel": "ORIGINAL",
    "create_time": "2023-11-02T16:29:47+08:00",
    "funds_account": "UNAVAILABLE",
    "out_refund_no": "refund213978a53c196395d3d1e8e33e167727",
    "out_trade_no": "213978a53c196395d3d1e8e33e167727",
    "promotion_detail": [],
    "refund_id": "50302107432023110202791108470",
    "status": "SUCCESS",
    "success_time": "2023-11-02T16:29:54+08:00",
    "transaction_id": "4200002026202311028784131594",
    "user_received_account": "支付用户零钱"
}
    * */
    public String queryRefundOrder(String outTradeNo) throws Exception{
        String bodyAsString="";
        try {
            PrivateKey merchantPrivateKey = PemUtil
                    .loadPrivateKey(new ByteArrayInputStream(private_key.getBytes("utf-8")));
            // 获取证书管理器实例
            CertificatesManager certificatesManager = CertificatesManager.getInstance();
            // 向证书管理器增加需要自动更新平台证书的商户信息
            certificatesManager.putMerchant(mchId,
                    new WechatPay2Credentials(mchId,
                            new PrivateKeySigner(mch_serial_no, merchantPrivateKey)),
                    key_v3.getBytes(StandardCharsets.UTF_8));
            CloseableHttpClient httpClient = WechatPayHttpClientBuilder.create()
                    .withMerchant(mchId, mch_serial_no, merchantPrivateKey)
                    .withValidator(new WechatPay2Validator(certificatesManager.getVerifier(mchId)))
                    .build();
            String outRefundNo="refund"+outTradeNo;
            URIBuilder uriBuilder = new URIBuilder("https://api.mch.weixin.qq.com/v3/refund/domestic/refunds/"+outRefundNo);
            HttpGet httpGet = new HttpGet(uriBuilder.build());
            httpGet.addHeader("Accept", "application/json");
            CloseableHttpResponse response = httpClient.execute(httpGet);
            bodyAsString = EntityUtils.toString(response.getEntity());
            System.out.println(bodyAsString);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bodyAsString;
    }
    /*退款*/
    public String createRefundOrder(String outTradeNo, int total, int refund) {
        try {
            PrivateKey merchantPrivateKey = PemUtil
                    .loadPrivateKey(new ByteArrayInputStream(private_key.getBytes("utf-8")));
            // 获取证书管理器实例
            CertificatesManager certificatesManager = CertificatesManager.getInstance();
            // 向证书管理器增加需要自动更新平台证书的商户信息
            certificatesManager.putMerchant(mchId,
                    new WechatPay2Credentials(mchId,
                            new PrivateKeySigner(mch_serial_no, merchantPrivateKey)),
                    key_v3.getBytes(StandardCharsets.UTF_8));

            CloseableHttpClient httpClient = WechatPayHttpClientBuilder.create()
                    .withMerchant(mchId, mch_serial_no, merchantPrivateKey)
                    .withValidator(new WechatPay2Validator(certificatesManager.getVerifier(mchId)))
                    .build();
            HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/refund/domestic/refunds");
            httpPost.addHeader("Accept", "application/json");
            httpPost.addHeader("Content-type", "application/json; charset=utf-8");

            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectMapper objectMapper = new ObjectMapper();

            ObjectNode rootNode = objectMapper.createObjectNode();
            //String outRefundNo = stringToMD5("refund"+outTradeNo);
            String outRefundNo = "refund"+outTradeNo;
            rootNode.put("out_refund_no", outRefundNo)
                    .put("notify_url", refund_notify_url)
                    .put("out_trade_no", outTradeNo);
            rootNode.putObject("amount")
                    .put("total", total)
                    .put("refund", refund)
                    .put("currency", "CNY");
            objectMapper.writeValue(bos, rootNode);
            httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));
            CloseableHttpResponse response = httpClient.execute(httpPost);

            String bodyAsString = EntityUtils.toString(response.getEntity());
            System.out.println(bodyAsString);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    /*分账请求*/
    public String createDivideOrder(String outTradeNo, String transactionId, JSONArray receivers) {
        try {
            PrivateKey merchantPrivateKey = PemUtil
                    .loadPrivateKey(new ByteArrayInputStream(private_key.getBytes("utf-8")));
            // 获取证书管理器实例
            CertificatesManager certificatesManager = CertificatesManager.getInstance();
            // 向证书管理器增加需要自动更新平台证书的商户信息
            certificatesManager.putMerchant(mchId,
                    new WechatPay2Credentials(mchId,
                            new PrivateKeySigner(mch_serial_no, merchantPrivateKey)),
                    key_v3.getBytes(StandardCharsets.UTF_8));

            CloseableHttpClient httpClient = WechatPayHttpClientBuilder.create()
                    .withMerchant(mchId, mch_serial_no, merchantPrivateKey)
                    .withValidator(new WechatPay2Validator(certificatesManager.getVerifier(mchId)))
                    .build();
            HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/profitsharing/orders");
            httpPost.addHeader("Accept", "application/json");
            httpPost.addHeader("Content-type", "application/json; charset=utf-8");

            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectMapper objectMapper = new ObjectMapper();



            JSONArray jsonArray=new JSONArray();
            //for(int i=0;i<receivers.size();i++){
                JSONObject jsonObject1=new JSONObject();
                jsonObject1.put("type","MERCHANT_ID");
                jsonObject1.put("account","1606601801");
                jsonObject1.put("amount",1);
                jsonObject1.put("description","测试分账");
                jsonArray.add(jsonObject1);
            //}
            outTradeNo="17036705599741101122";
            transactionId="4200002079202312288691877800";
            JSONObject jsonObject=new JSONObject();
            jsonObject.put("appid", appid);
            jsonObject.put("transaction_id", transactionId);
            jsonObject.put("out_order_no", outTradeNo);
            jsonObject.put("receivers", jsonArray);
            jsonObject.put("unfreeze_unsplit", true);
            httpPost.setEntity(new StringEntity(jsonObject.toString(), "UTF-8"));
            CloseableHttpResponse response = httpClient.execute(httpPost);
            System.out.println(jsonObject.toString());
            String bodyAsString = EntityUtils.toString(response.getEntity());

            System.out.println(bodyAsString);
            return bodyAsString;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }
    /*
    查询分账结果
     */
    public String queryDivideOrder(String outTradeNo) throws Exception{
        String bodyAsString="";
        try {
            PrivateKey merchantPrivateKey = PemUtil
                    .loadPrivateKey(new ByteArrayInputStream(private_key.getBytes("utf-8")));
            // 获取证书管理器实例
            CertificatesManager certificatesManager = CertificatesManager.getInstance();
            // 向证书管理器增加需要自动更新平台证书的商户信息
            certificatesManager.putMerchant(mchId,
                    new WechatPay2Credentials(mchId,
                            new PrivateKeySigner(mch_serial_no, merchantPrivateKey)),
                    key_v3.getBytes(StandardCharsets.UTF_8));
            CloseableHttpClient httpClient = WechatPayHttpClientBuilder.create()
                    .withMerchant(mchId, mch_serial_no, merchantPrivateKey)
                    .withValidator(new WechatPay2Validator(certificatesManager.getVerifier(mchId)))
                    .build();
            outTradeNo="17036705599741101122";
            String transactionId="4200002079202312288691877800";
            URIBuilder uriBuilder = new URIBuilder("https://api.mch.weixin.qq.com/v3/profitsharing/orders/"+outTradeNo+"?transaction_id="+transactionId);
            HttpGet httpGet = new HttpGet(uriBuilder.build());
            httpGet.addHeader("Accept", "application/json");
            CloseableHttpResponse response = httpClient.execute(httpGet);
            bodyAsString = EntityUtils.toString(response.getEntity());
            System.out.println(bodyAsString);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bodyAsString;
    }

    /*增加分账人*/
    public String addDividUser() {
        try {
            PrivateKey merchantPrivateKey = PemUtil
                    .loadPrivateKey(new ByteArrayInputStream(private_key.getBytes("utf-8")));
            // 获取证书管理器实例
            CertificatesManager certificatesManager = CertificatesManager.getInstance();
            // 向证书管理器增加需要自动更新平台证书的商户信息
            certificatesManager.putMerchant(mchId,
                    new WechatPay2Credentials(mchId,
                            new PrivateKeySigner(mch_serial_no, merchantPrivateKey)),
                    key_v3.getBytes(StandardCharsets.UTF_8));

            CloseableHttpClient httpClient = WechatPayHttpClientBuilder.create()
                    .withMerchant(mchId, mch_serial_no, merchantPrivateKey)
                    .withValidator(new WechatPay2Validator(certificatesManager.getVerifier(mchId)))
                    .build();
            HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/profitsharing/receivers/add");
            httpPost.addHeader("Accept", "application/json");
            httpPost.addHeader("Content-type", "application/json; charset=utf-8");
            JSONObject jsonObject=getPlatformKey();
            String serialNo=jsonObject.getJSONArray("data").
                    getJSONObject(0).getString("serial_no");
            String publicKey=jsonObject.getJSONArray("data").
                    getJSONObject(0).
                    getJSONObject("encrypt_certificate").
                    getString("ciphertext");
            logger.error("serialNo="+serialNo);
            logger.error("publicKey="+publicKey);
            httpPost.addHeader("Wechatpay-Serial", serialNo);
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectMapper objectMapper = new ObjectMapper();

            ObjectNode rootNode = objectMapper.createObjectNode();
            //String outRefundNo = stringToMD5("refund"+outTradeNo);
            rootNode.put("appid", appid)
                    .put("type", "PERSONAL_OPENID")
                    .put("account", "ofMKV6z5NOOQ14BBIZYwQdJofiWg")
                    .put("relation_type", "PARTNER")
                    .put("name", rsaEncryptOAEP("梁里福",publicKey));
            objectMapper.writeValue(bos, rootNode);
            httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));
            CloseableHttpResponse response = httpClient.execute(httpPost);
            String bodyAsString = EntityUtils.toString(response.getEntity());
            System.out.println(bodyAsString);
            return bodyAsString;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    /*删除分账人*/
    public String deleteDividUser() {
        try {
            PrivateKey merchantPrivateKey = PemUtil
                    .loadPrivateKey(new ByteArrayInputStream(private_key.getBytes("utf-8")));
            // 获取证书管理器实例
            CertificatesManager certificatesManager = CertificatesManager.getInstance();
            // 向证书管理器增加需要自动更新平台证书的商户信息
            certificatesManager.putMerchant(mchId,
                    new WechatPay2Credentials(mchId,
                            new PrivateKeySigner(mch_serial_no, merchantPrivateKey)),
                    key_v3.getBytes(StandardCharsets.UTF_8));

            CloseableHttpClient httpClient = WechatPayHttpClientBuilder.create()
                    .withMerchant(mchId, mch_serial_no, merchantPrivateKey)
                    .withValidator(new WechatPay2Validator(certificatesManager.getVerifier(mchId)))
                    .build();
            HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/profitsharing/receivers/delete");
            httpPost.addHeader("Accept", "application/json");
            httpPost.addHeader("Content-type", "application/json; charset=utf-8");

            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectMapper objectMapper = new ObjectMapper();

            ObjectNode rootNode = objectMapper.createObjectNode();
            //String outRefundNo = stringToMD5("refund"+outTradeNo);
            rootNode.put("appid", appid)
                    .put("type", "PERSONAL_OPENID")
                    .put("account", "ofMKV6z5NOOQ14BBIZYwQdJofiWg");
            objectMapper.writeValue(bos, rootNode);
            httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));
            CloseableHttpResponse response = httpClient.execute(httpPost);
            String bodyAsString = EntityUtils.toString(response.getEntity());
            System.out.println(bodyAsString);
            return bodyAsString;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    /*message为appId、timeStamp、nonceStr、package拼接成的字符串 计算得出paySign*/
    String sign(byte[] message) throws Exception{
        try {
            PrivateKey merchantPrivateKey = PemUtil
                    .loadPrivateKey(new ByteArrayInputStream(private_key.getBytes("utf-8")));
            Signature sign = Signature.getInstance("SHA256withRSA");
            sign.initSign(merchantPrivateKey);
            sign.update(message);
            return Base64.getEncoder().encodeToString(sign.sign());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static String stringToMD5(String plainText) {
        byte[] secretBytes = null;
        try {
            secretBytes = MessageDigest.getInstance("md5").digest(plainText.getBytes());
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("Secret Failed");
        }
        String md5code = new BigInteger(1, secretBytes).toString(16);
        for (int i = 0; i < 32 - md5code.length(); i++) {
            md5code = "0" + md5code;
        }
        return md5code;
    }

    public  String getOutTradeNo(){
        Long times= System.currentTimeMillis();
        String key = "wx_OutTradeNo_key" ;
        Object obj=redisTemplate.opsForValue().get(key);
        Long id=0L;
        if(obj==null){
            redisTemplate.opsForValue().set(key,times);
            id=redisTemplate.opsForValue().increment(key,1);
        }else{
            id=redisTemplate.opsForValue().increment(key,1);
        }
        return ""+id+RandomUtil.randomNumbers(7);
    }

    public  String rsaEncryptOAEP(String name,String publicKey)
            throws Exception {
        try {
            System.out.println(publicKey);
            byte[] decodedBytes = Base64.getDecoder().decode(publicKey);
            PrivateKey privateKey = PemUtil
                    .loadPrivateKey(new ByteArrayInputStream(decodedBytes));
            Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding");
            cipher.init(Cipher.DECRYPT_MODE, privateKey);

            byte[] data = Base64.getDecoder().decode(name);
            return new String(cipher.doFinal(data), "utf-8");
        } catch (NoSuchPaddingException | NoSuchAlgorithmException e) {
            throw new RuntimeException("当前Java环境不支持RSA v1.5/OAEP", e);
        } catch (InvalidKeyException e) {
            throw new IllegalArgumentException("无效的私钥", e);
        } catch (BadPaddingException | IllegalBlockSizeException e) {
            throw new BadPaddingException("解密失败");
        }
    }

    /*
   查询分账结果
    */
    public JSONObject getPlatformKey() throws Exception{
        JSONObject bodyAsString=null;
        try {
            PrivateKey merchantPrivateKey = PemUtil
                    .loadPrivateKey(new ByteArrayInputStream(private_key.getBytes("utf-8")));
            // 获取证书管理器实例
            CertificatesManager certificatesManager = CertificatesManager.getInstance();
            // 向证书管理器增加需要自动更新平台证书的商户信息
            certificatesManager.putMerchant(mchId,
                    new WechatPay2Credentials(mchId,
                            new PrivateKeySigner(mch_serial_no, merchantPrivateKey)),
                    key_v3.getBytes(StandardCharsets.UTF_8));
            CloseableHttpClient httpClient = WechatPayHttpClientBuilder.create()
                    .withMerchant(mchId, mch_serial_no, merchantPrivateKey)
                    .withValidator(new WechatPay2Validator(certificatesManager.getVerifier(mchId)))
                    .build();
            URIBuilder uriBuilder = new URIBuilder("https://api.mch.weixin.qq.com/v3/certificates");
            HttpGet httpGet = new HttpGet(uriBuilder.build());
            httpGet.addHeader("Accept", "application/json");
            httpGet.addHeader("User-Agent", "用户代理(https://zh.wikipedia.org/wiki/User_agent)");
            CloseableHttpResponse response = httpClient.execute(httpGet);
            String bodyAsString2 = EntityUtils.toString(response.getEntity());
            System.out.println(bodyAsString);
            bodyAsString=JSONObject.parseObject(bodyAsString2);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bodyAsString;
    }

}
